/*-------------------------------------------------------------------------
 *
 * relfilenode.h
 *	  关系的物理访问信息。
 *
 *
 * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
 * Portions Copyright (c) 1994, Regents of the University of California
 *
 * src/include/storage/relfilenode.h
 *
 *-------------------------------------------------------------------------
 */
#ifndef RELFILENODE_H
#define RELFILENODE_H

#include "common/relpath.h"
#include "storage/backendid.h"

/*
 * RelFileNode 必须提供我们所需的所有信息，以物理访问一个关系，
 * 除了后端 ID 外，可以单独提供。不过请注意，“物理”关系由多个
 * 文件组成，因为每个分支作为一个单独的文件存储，每个分支可以分
 * 成多个段。请参阅 md.c。
 *
 * spcNode标识关系的表空间。它对应 pg_tablespace.oid。
 *
 * dbNode 标识关系的数据库。对“共享”关系（对集群所有数据库
 * 通用的关系），它为零。非零的 dbNode 值对应于 pg_database.oid。
 *
 * relNode 标识特定关系。relNode 对应于 pg_class.relfilenode
 * （而不是 pg_class.oid，因为在某些情况下我们需要能够将新的物理
 * 文件分配给关系）。注意，relNode 仅在特定表空间内的数据库中是
 * 唯一的。
 *
 * 注意：如果且仅当 dbNode 为零时，spcNode 必须为 GLOBALTABLESPACE_OID。
 * 我们仅在“全局”表空间中支持共享关系。
 *
 * 注意：在 pg_class 中，我们允许 reltablespace == 0 表示关系
 * 存储在其数据库的“默认”表空间中（由 pg_database.dattablespace 
 * 标识）。然而，这种简写在 RelFileNode 结构中不被允许——设置
 * spcNode 时必须提供真实的表空间 ID。
 *
 * 注意：在 pg_class 中，relfilenode 可以为零，以表示关系是一个
 * “映射的”关系，其当前真实的 filenode 编号可以从 relmapper.c
 * 中获得。同样，这种情况在 RelFileNodes 中不被允许。
 *
 * 注意：在许多地方将 RelFileNode 用作哈希表键。因此，此结构中
 * 不允许有任何未使用的填充字节。只要所有字段都是 Oid 类型，这应该是安全的。
 */
typedef struct RelFileNode
{
	Oid			spcNode;		/* 表空间 */
	Oid			dbNode;			/* database */
	Oid			relNode;		/* 关系 */
} RelFileNode;

/*
 * 用后端 ID 扩展 relfilenode 提供了我们定位物理存储所需的
 * 所有信息。对于常规关系（即可被多个后端访问），后端 ID 为
 * InvalidBackendId，或者对于后端本地关系，使用拥有后端的 ID。
 * 后端本地关系始终是临时的，在数据库崩溃时删除；它们不
 * 会被 WAL 记录或 fsync。
 */
typedef struct RelFileNodeBackend
{
	RelFileNode node;
	BackendId	backend;
} RelFileNodeBackend;

#define RelFileNodeBackendIsTemp(rnode) \
	((rnode).backend != InvalidBackendId)

/*
 * 注意：RelFileNodeEquals 和 RelFileNodeBackendEquals 首先比较
 * relNode，因为这是两个不等 RelFileNodes 中最有可能不同的部分。
 * 如果发现其他字段相等，比较 spcNode 可能是多余的，但还是要
 * 确保。对 RelFileNodeBackendEquals 中检查后端 ID 同样如此。
 */
#define RelFileNodeEquals(node1, node2) \
	((node1).relNode == (node2).relNode && \
	 (node1).dbNode == (node2).dbNode && \
	 (node1).spcNode == (node2).spcNode)

#define RelFileNodeBackendEquals(node1, node2) \
	((node1).node.relNode == (node2).node.relNode && \
	 (node1).node.dbNode == (node2).node.dbNode && \
	 (node1).backend == (node2).backend && \
	 (node1).node.spcNode == (node2).node.spcNode)

#endif							/* RELFILENODE_H */
